package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
	"syscall"
)

const BasicFile = "Name: \nTags: \nImage: \nDescription:\n"

type Config struct {
	dbPath string
	editor string
	basicFile string
	downloadResources bool
}


func readConf() (*Config, error) {
	var err error
	conf := &Config{
		dbPath: os.Getenv("HOME") + "/.recp",
		editor: defaultEditor(),
		basicFile: BasicFile,
		downloadResources: true,
	}
	if runtime.GOOS == "windows" {
		conf.basicFile = strings.Replace(conf.basicFile, 
						 "\n", "\r\n", -1)
	}
	err = conf.readConfigFile()
	if err != nil {
		return nil, err
	}
	return conf, nil
}


func defaultEditor() string {
	ed := os.Getenv("EDITOR")
	if ed != "" {
		return ed
	}

	switch runtime.GOOS {
	case "windows":
		return os.Getenv("windir") + `\notepad.exe`
	default:
		return "/usr/bin/vi"
	}

	panic("unreachable code")
}


func (conf *Config) readConfigFile() error {
	// if the file does not exist, create it
	if _, err := os.Stat(os.Getenv("HOME") + "/.config/recp.conf"); 
	err != syscall.ENOENT {
		if err := conf.createConfigFile(); err != nil {
			return err
		}
	}

	// open file
	fi, err := os.Open(os.Getenv("HOME") + "/.config/recp.conf")
	if err != nil {
		return err
	}
	defer fi.Close()
	buf := bufio.NewReader(fi)
	_ = buf
	
	// read file
	var s string
	err = nil
	for err != io.EOF {
		s, err = buf.ReadString('\n')
		s = strings.Trim(s, "\n")
		if strings.Trim(strings.Trim(s, " "), "\t") == "" {
			continue
		}
		s = strings.SplitN(s, "#", 2)[0]  // remove comments
		kv := strings.SplitN(s, "=", 2)
		if len(kv) != 2 {
			return &InvalidConfigSyntaxError{}
		}
		k, v := strings.Trim(kv[0], " "), strings.Trim(kv[1], " ")
		switch k {
		case "db_path": 
			conf.dbPath = v
		case "editor":
			conf.editor = v
		case "download_resources":
			if v == "true" {
				conf.downloadResources = true
			} else if v == "false" {
				conf.downloadResources = false
			} else {
				fmt.Println(v)
				return &InvalidConfigSyntaxError{}
			}
		}
	}

	return nil
}


func (conf *Config) createConfigFile() error {
	os.Mkdir(os.Getenv("HOME") + "/.config", 0666)
	fi, err := os.Create(os.Getenv("HOME") + "/.config/recp.conf")
	if err != nil {
		return err 
	}
	defer fi.Close()
	buf := bufio.NewWriter(fi)

	fmt.Fprintf(buf, "db_path            = %s\n", conf.dbPath);
	fmt.Fprintf(buf, "editor             = %s\n", conf.editor);
	if conf.downloadResources {
		fmt.Fprintf(buf, "download_resources = true\n");
	} else {
		fmt.Fprintf(buf, "download_resources = false\n");
	}
	buf.Flush()

	return nil
}


type InvalidConfigSyntaxError struct {}
func (e *InvalidConfigSyntaxError) Error() string { return "Invalid syntax of config file." }
